Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always use getDocument in FocusZone and FocusTrapZone #10187

Merged

Conversation

sophieH29
Copy link
Contributor

@sophieH29 sophieH29 commented Aug 19, 2019

Pull request checklist

  • Include a change request file using $ yarn change

Description of changes

Use getDocument instead of document object to keep consistency and be less error-prone.

Use case:
When rendering components (for e.g. FocusZone and FocusTrapZone) in an external window using window.open, document object will be used incorrectly as it is taken from the parent window not from the current.
A code example of PortalWindow when render child components there

const PortalWindow = ({ children, onClose }) => {
  const externalContainer = React.useRef(null);
  const externalWindow = React.useRef(null);
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => {
    externalWindow.current = window.open(
      "",
      "",
      "width=600,height=400,left=200,top=200"
    );
    externalContainer.current = externalWindow.current.document.createElement(
      "div"
    );
    externalWindow.current.document.body.appendChild(externalContainer.current);
    if (onClose) externalWindow.current.onbeforeunload = onClose;
    setMounted(true);
    return () => {
      externalWindow.current.close();
    };
  }, []);
  return (
    mounted &&
    ReactDOM.createPortal(
      children(externalContainer.current.ownerDocument),
      externalContainer.current
    )
  );
};

https://codesandbox.io/s/stardust-ui-example-1phxh

Microsoft Reviewers: Open in CodeFlow

@msftclas
Copy link

msftclas commented Aug 19, 2019

CLA assistant check
All CLA requirements met.

@sophieH29 sophieH29 changed the title Sohuts/use getdocument in focuszone Always use getDocument in FocusZone and FocusTrapZone Aug 19, 2019
@size-auditor
Copy link

size-auditor bot commented Aug 19, 2019

Bundle test Size (minified) Diff from master
Dialog 192.171 kB ExceedsBaseline     239 bytes
DatePicker 201.355 kB ExceedsBaseline     239 bytes
Dropdown 214.497 kB ExceedsBaseline     239 bytes
Panel 184.157 kB ExceedsBaseline     239 bytes
FocusTrapZone 16.284 kB ExceedsBaseline     216 bytes
ContextualMenu 147.799 kB ExceedsBaseline     128 bytes
FocusZone 34.331 kB ExceedsBaseline     128 bytes
ExtendedPicker 86.86 kB ExceedsBaseline     128 bytes
Calendar 144.976 kB ExceedsBaseline     128 bytes
ComboBox 225.253 kB ExceedsBaseline     128 bytes
OverflowSet 56.237 kB ExceedsBaseline     128 bytes
DetailsList 209.615 kB ExceedsBaseline     128 bytes
GroupedList 120.499 kB ExceedsBaseline     126 bytes
Pivot 172.692 kB ExceedsBaseline     126 bytes
Pickers 263.179 kB ExceedsBaseline     126 bytes
Nav 173.793 kB ExceedsBaseline     126 bytes
DocumentCard 199.584 kB ExceedsBaseline     126 bytes
MessageBar 174.875 kB ExceedsBaseline     126 bytes
Facepile 195.451 kB ExceedsBaseline     126 bytes
FloatingPicker 222.764 kB ExceedsBaseline     126 bytes
Grid 167.385 kB ExceedsBaseline     126 bytes
Rating 73.664 kB ExceedsBaseline     126 bytes
CommandBar 186.052 kB ExceedsBaseline     126 bytes
SwatchColorPicker 177.222 kB ExceedsBaseline     126 bytes
SearchBox 173.182 kB ExceedsBaseline     126 bytes
Button 179.141 kB ExceedsBaseline     126 bytes
SelectedItemsList 213.007 kB ExceedsBaseline     126 bytes
TeachingBubble 178.09 kB ExceedsBaseline     126 bytes
ShimmeredDetailsList 220.183 kB ExceedsBaseline     126 bytes
Breadcrumb 184.004 kB ExceedsBaseline     126 bytes
SpinButton 178.629 kB ExceedsBaseline     126 bytes
HoverCard 98.656 kB ExceedsBaseline     113 bytes
Coachmark 96.554 kB ExceedsBaseline     113 bytes
Modal 93.338 kB ExceedsBaseline     113 bytes
Callout 83.67 kB ExceedsBaseline     112 bytes

ExceedsTolerance  Exceeds Tolerance     ExceedsBaseline  Exceeds Baseline     BelowBaseline  Below Baseline     1 kB = 1000 bytes

@msft-github-bot
Copy link
Contributor

msft-github-bot commented Aug 19, 2019

Component Perf Analysis:

Scenario Master Samples * PR Samples *
BaseButton 795 737
BaseButton (experiments) 1074 1089
DefaultButton 1041 1043
DefaultButton (experiments) 1955 1983
DetailsRow 3373 3408
DetailsRow (fast icons) 3372 3397
DetailsRow without styles 3052 3175
DocumentCardTitle with truncation 33016 33003
MenuButton 1841 1922
MenuButton (experiments) 4003 4033
PrimaryButton 1205 1220
PrimaryButton (experiments) 2105 2038
SplitButton 3469 3467
SplitButton (experiments) 7598 7592
Stack 480 472
Stack with Intrinsic children 1132 1115
Stack with Text children 4301 4236
Text 385 400
Toggle 878 908
Toggle (experiments) 2318 2295
button 67 67
* Sample counts can vary by up to 30% and shouldn't be used solely for determining regression. For more information please see the Perf Testing wiki.

@@ -277,7 +280,8 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl
}

if (FocusTrapZone._focusStack.length && this === FocusTrapZone._focusStack[FocusTrapZone._focusStack.length - 1]) {
const focusedElement = document.activeElement as HTMLElement;
const doc = getDocument(this._root.current);
const focusedElement = doc!.activeElement as HTMLElement;
Copy link
Member

@JasonGore JasonGore Aug 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are enough uses here that it's worthwhile to make a little helper function and call it directly while eliminating the need for intermediate local doc variables. Something like:

private getDocument() {
  return getDocument(this._root.current);
}

Copy link
Contributor Author

@sophieH29 sophieH29 Aug 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. But still, make sense to remain in places were doc variable is used multiple times within a function scope

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JasonGore addressed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't there more replaceable instances above? I only see once case where it's actually used more than once.

Copy link
Contributor Author

@sophieH29 sophieH29 Aug 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced all document.* usage with _getDocument().*.In 2 places in FocusZone and and 1 place in FocusTrapZone I saved it to variable const doc = this._getDocument(); and used as doc.* because it is used more than once within the function scope. Let me know if it does make sense


const doc = this._getDocument();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is important, otherwise, SSR tests will fail

@msft-github-bot
Copy link
Contributor

🎉office-ui-fabric-react@v7.26.0 has been released which incorporates this pull request.:tada:

Handy links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants